package com.demo.arch.datapulsedemo.v2_pipeline.core;

import com.demo.arch.datapulsedemo.common.NotificationRecipient;
import com.demo.arch.datapulsedemo.common.OrderData;
import lombok.Data;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 流程上下文 - 数据在管道中流动的容器
 * 
 * 核心思想：
 * - 携带所有步骤需要的数据
 * - 每个步骤更新自己负责的数据
 * - 步骤间通过Context解耦
 * 
 * @author DataPulse Team
 */
@Data
public class PipelineContext implements Serializable {
  private static final long serialVersionUID = 1L;

  // ========== 任务标识 ==========

  /**
   * 任务唯一ID
   */
  private String taskId;

  /**
   * 任务创建时间
   */
  private LocalDateTime createTime;

  // ========== 输入参数 ==========

  /**
   * 报表类型（输入参数）
   */
  private String reportType;

  /**
   * 扩展参数
   */
  private Map<String, Object> params;

  // ========== 步骤1：查询数据 ==========

  /**
   * 查询到的订单数据
   */
  private List<OrderData> orderData;

  // ========== 步骤2：生成Excel ==========

  /**
   * 生成的Excel文件路径
   */
  private String excelFilePath;

  // ========== 步骤3：获取收件人 ==========

  /**
   * 通知接收人列表
   */
  private List<NotificationRecipient> recipients;

  // ========== 步骤4：发送邮件 ==========

  /**
   * 邮件主题
   */
  private String emailSubject;

  /**
   * 邮件内容
   */
  private String emailContent;

  /**
   * 发送成功数量
   */
  private Integer emailSuccessCount;

  /**
   * 发送失败数量
   */
  private Integer emailFailCount;

  /**
   * 成功发送的邮箱集合（用于幂等性检查）
   */
  private Set<String> successEmails;

  /**
   * 错误信息
   */
  private String errorMessage;

  // ========== 流程控制 ==========

  /**
   * 当前执行步骤（用于断点续跑）
   */
  private Integer currentStep;

  // ========== 元数据 ==========

  /**
   * 扩展数据存储（用于步骤间传递自定义数据）
   */
  private Map<String, Object> metadata;

  // ========== 构造方法 ==========

  public PipelineContext() {
    this.params = new HashMap<>();
    this.metadata = new HashMap<>();
    this.createTime = LocalDateTime.now();
  }

  public PipelineContext(String reportType) {
    this();
    this.reportType = reportType;
  }

  // ========== 便捷方法 ==========

  /**
   * 从metadata中获取数据
   */
  @SuppressWarnings("unchecked")
  public <T> T get(String key) {
    return (T) metadata.get(key);
  }

  /**
   * 向metadata中存储数据
   */
  public void put(String key, Object value) {
    metadata.put(key, value);
  }

  /**
   * 判断是否包含某个key
   */
  public boolean contains(String key) {
    return metadata.containsKey(key);
  }
}
